#include "string.h"
#include "stdio.h"
#include <stdlib.h>
/* 接口库 */
#include "CompressorMotor.hpp"
#include "crc.h"

/* 工具函数  */
uint16_t compressorMotorAdjustSequence(uint16_t value) {
    if( sizeof(value) == 1){
        return value;
    }
    else
    return (value >> 8) | (value << 8);
}

/* 当前类资源 */
static struct CompressorMotorResource {
    CompressorMotor *instance;
    unsigned char compressor_packets[sizeof(CompressorMotor::RequestProtocol_t)];    //Compressor协议包
    unsigned char receive_buffer[64];     //数据接收缓冲区
    CompressorMotor::RequestProtocol_t * request_content = nullptr;  //数据请求协议包
    CompressorMotor::ResponseProtocol_t * response_content = nullptr;   //数据应答协议包

} compressor_motor_resource = {
    .instance = nullptr,
    .compressor_packets = {0},
    .receive_buffer = {0},
    .request_content = (CompressorMotor::RequestProtocol_t * ) compressor_motor_resource.compressor_packets,
    .response_content = (CompressorMotor::ResponseProtocol_t * ) compressor_motor_resource.receive_buffer,
};

/* 相关类的定义以及方法实现 */
class __Adapter : public CompressorMotor::Adapter{
    public:
        virtual bool open(void);
        virtual bool close(void);
        virtual unsigned int read(void *buffer,unsigned int size);
        virtual unsigned int write(void *buffer,unsigned int size);
};

bool __Adapter::open(void){
    printf("adapter open\r\n");
    return true;
}

bool __Adapter::close(void){
    printf("adapter close\r\n");
    return true;    
}

unsigned int __Adapter::write(void *buffer,unsigned int size){
    unsigned char * data  = (unsigned char * )buffer;
    for ( int i = 0; i < size; i++){
        printf("%02X ",data[i]);
    }
    return size;
}

unsigned int __Adapter::read(void *buffer,unsigned int size){
    unsigned int length = 0;
    unsigned char *buf = (unsigned char *)buffer;

    char hexBuffer[3] = {0};
    while ( true ) {
        unsigned char ch = getchar();
        if (ch == ' ' || ch == '\t') {
            continue;
        }
        if ( ch == '\n' ) break;
        hexBuffer[length % 2] = ch;
        if (length % 2 == 1) {
            buf[length / 2] = (unsigned char)strtol(hexBuffer, NULL, 16);
        }
        length++;
    }
    return length / 2;  // 返回接收到的字节数
}

CompressorMotor :: CompressorMotor(Adapter *adapter){
    if( adapter != nullptr ){
        this->adapter = adapter;
    }
}

CompressorMotor :: ~CompressorMotor(){}

CompressorMotor * CompressorMotor::getInstance(void){
    if( compressor_motor_resource.instance == nullptr ){
        Adapter * adapter = new __Adapter();
        if( adapter != nullptr ){
            compressor_motor_resource.instance = new CompressorMotor(adapter);
        }
    }
    return compressor_motor_resource.instance;
}

/*************************************  方法实现 **************************************/
/* 构建数据包 */
bool CompressorMotor::buildPackets(uint8_t RW,uint8_t slave_address , uint16_t access_address , uint16_t access_data){

    compressor_motor_resource.request_content->slave_address = slave_address;
    compressor_motor_resource.request_content->function_code = RW;
    compressor_motor_resource.request_content->access_address = compressorMotorAdjustSequence(access_address);
    compressor_motor_resource.request_content->access_data = compressorMotorAdjustSequence(access_data);
    compressor_motor_resource.request_content->crc = crc16((uint8_t *)compressor_motor_resource.request_content,sizeof(CompressorMotor::RequestProtocol_t) - sizeof(compressor_motor_resource.request_content->crc));
   
    return true;

}

/* 处理写入的应答数据 */
bool CompressorMotor::checkResponse(void){

    uint8_t length = 0;
    int count = 0;
    while( count < 1000 ){
        length = this->adapter->read(compressor_motor_resource.receive_buffer,0);
        if ( length > 0) break;
        count ++;
    }

    if( length > 0 && length == sizeof(CompressorMotor::RequestProtocol_t)){
        if (memcmp(compressor_motor_resource.receive_buffer, compressor_motor_resource.compressor_packets, sizeof(CompressorMotor::RequestProtocol_t)) == 0) {
            memset(compressor_motor_resource.compressor_packets,0,sizeof(compressor_motor_resource.compressor_packets));
            memset(compressor_motor_resource.receive_buffer,0,sizeof(compressor_motor_resource.receive_buffer));
            return true;
        }        
    }
    memset(compressor_motor_resource.compressor_packets,0,sizeof(compressor_motor_resource.compressor_packets));
    memset(compressor_motor_resource.receive_buffer,0,sizeof(compressor_motor_resource.receive_buffer));
    return false;
}

/**
 * @brief 处理读取的应答数据
 * @return 正常返回读取的数据,否则返回相应的错误码
 */
uint16_t CompressorMotor::processResponse(void){
    uint8_t length = 0;
    uint16_t read_value = 0;
    int count = 0;
    while( count < 10 ){
        length = this->adapter->read(compressor_motor_resource.receive_buffer,0);
        if ( length > 0) break;
        count ++;
    }
    // printf("length:%d\r\n",length);
    if( length == 0 || length != sizeof(CompressorMotor::ResponseProtocol_t)) return CompressorMotor::ResponseErrorType_LengthError;
    if( compressor_motor_resource.request_content->slave_address != compressor_motor_resource.response_content->slave_address) return CompressorMotor::ResponseErrorType_AddressError;
    if( compressor_motor_resource.request_content->function_code != compressor_motor_resource.response_content->function_code) return CompressorMotor::ResponseErrorType_FunctionError;
    if( compressor_motor_resource.response_content->crc != crc16((uint8_t *)compressor_motor_resource.response_content,sizeof(CompressorMotor::ResponseProtocol_t) - sizeof(compressor_motor_resource.response_content->crc))) return CompressorMotor::ResponseErrorType_CRCError;

    read_value = compressor_motor_resource.response_content->register_value;
    /* 清空数据缓冲区 */
    memset(compressor_motor_resource.request_content,0,sizeof(compressor_motor_resource.request_content));
    memset(compressor_motor_resource.receive_buffer,0,sizeof(compressor_motor_resource.receive_buffer));
    /* 调整端序 返回正确数据 */
    read_value = compressorMotorAdjustSequence(read_value);
    return read_value;    
}

/******************************************* 数据写入 *******************************************/
/**
 * @brief 使能电机 控制方式为通讯控制
 */
bool CompressorMotor::enableMotor(void) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_ControlMode, Data_0);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

/**
 * @brief 取消使能电机 控制方式为模拟指令
 */
bool CompressorMotor::disableMotor(void) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_ControlMode, Data_1);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

/**
 * @brief 控制命令:开机
 */
bool CompressorMotor::open(void) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_ControlCMD, Data_1);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

/**
 * @brief 控制命令:关机
 */
bool CompressorMotor::close(void) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_ControlCMD, Data_0);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

bool CompressorMotor::setSpeed(uint16_t speed) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_SpeedSet, speed);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

bool CompressorMotor::corotationMotor(void) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_RunDirection, Data_0);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

bool CompressorMotor::reversalMotor(void) {
    if (this->adapter == nullptr) {
        return false;
    }
    buildPackets(FunctionCode_WriteFun, SlaveAddress_DefaultAddress, RegisterAddress_RunDirection, Data_1);
    this->adapter->write(compressor_motor_resource.compressor_packets, sizeof(RequestProtocol_t));
    bool check_response = this->checkResponse();
    return check_response;
}

/******************************************* 数据写入 *******************************************/

uint16_t CompressorMotor::getControlMode(void){
    return 0;
}

uint16_t CompressorMotor::getControlCMD(void){
    return 0;
}

uint16_t CompressorMotor::getSpeedSet(void){
    if ( this->adapter == nullptr ){
        return ResponseErrorType_DefaultError;
    }
    buildPackets(FunctionCode_ReadFun,SlaveAddress_DefaultAddress,RegisterAddress_SpeedSet,Data_0);
    this->adapter->write(compressor_motor_resource.compressor_packets , sizeof(RequestProtocol_t));
    uint16_t speed = this->processResponse();
    return speed;

}

uint16_t CompressorMotor::getRunDirection(void){
    if ( this->adapter == nullptr ){
        return ResponseErrorType_DefaultError;
    }
    buildPackets(FunctionCode_ReadFun,SlaveAddress_DefaultAddress,RegisterAddress_SpeedActual,Data_0);
    this->adapter->write(compressor_motor_resource.compressor_packets , sizeof(RequestProtocol_t));
    uint16_t speed = this->processResponse();
    return speed;
}

uint16_t CompressorMotor::getSpeedActual(void){
    return 0;
}

uint16_t CompressorMotor::getBusVoltage(void){
    return 0;
}

